/**
 * 
 */
package com.glm.wwii.battleships.gamelogic;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;


import org.andengine.audio.music.Music;
import org.andengine.audio.sound.Sound;
import org.andengine.engine.Engine;
import org.andengine.engine.camera.Camera;
import org.andengine.entity.IEntity;
import org.andengine.entity.modifier.LoopEntityModifier;
import org.andengine.entity.modifier.PathModifier;
import org.andengine.entity.modifier.PathModifier.IPathModifierListener;
import org.andengine.entity.modifier.PathModifier.Path;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.sprite.TiledSprite;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.texture.ITexture;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.TextureRegion;
import org.andengine.opengl.texture.region.TextureRegionFactory;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.opengl.util.GLState;
import org.andengine.ui.activity.BaseGameActivity;

import org.andengine.util.modifier.ease.EaseSineInOut;

import com.glm.wwii.battleships.defence.Const.ConstValue;
import com.glm.wwii.battleships.enemy.Corvet;
import com.glm.wwii.battleships.enemy.Destroyer;
import com.glm.wwii.battleships.gamelogic.level.LevelPath;

import android.content.Context;
import android.util.Log;


/**
 * @author utente
 * @param <mTexture>
 *
 */
public class CoreGame<mTexture> {
	/**classse che si occupa del caricamento delle immagini nella VRAM*/
	ResourceLoader mResource;
	/**scena principale*/
	private Scene mScene;
	/**application context*/
	private Context mContext;
	/**hashtable col le texture da caricare*/
	private Hashtable<String, ITexture> mTextureTable;
	/**hashtable col le texture region caricate*/
	private Hashtable<String, TextureRegion> mTextureRegionTable=new Hashtable<String, TextureRegion>();
	/**HashTable contenente tutti i suoni FX*/
	private Hashtable<String, Sound> mSoundTable= new Hashtable<String, Sound>();
	/**HashTable contenente tutti le musiche*/
	private Hashtable<String, Music> mMusicTable= new Hashtable<String, Music>();
	/**Activity di base*/
	private BaseGameActivity mBaseGame;
	/**Contiene le stringhe con tutte le risorse da caricare*/
	private Enumeration<String> mTexture;
	private int mHeight,mWidth;
	
	/**
	 * Costruttore per la classe che si occupera' di gestire la scena
	 * 
	 * @author Gianluca Masci aka GLM
	 * @param oBaseGame 
	 * @param cameraWidth 
	 * @param cameraHeight 
	 * 
	 * @param Scene oSceneGame scena del game da gestire
	 * @param Context oContext 
	 * */
	public CoreGame(Context oContext, BaseGameActivity oBaseGame, int cameraHeight, int cameraWidth){
		this.mResource = new ResourceLoader(this.mContext,this.mBaseGame);
		this.mContext=oContext;		
		this.mBaseGame=oBaseGame;
		this.mHeight=cameraHeight;
		this.mWidth=cameraWidth;
	}
	
	public void LoadGameResource(){		
		mTextureTable=this.mResource.loadGameTexture(this.mContext,this.mBaseGame);			
		mTexture = mTextureTable.keys(); 
		while(mTexture.hasMoreElements()) { 
			String sTextureName = (String) mTexture.nextElement(); 			
			mTextureTable.get(sTextureName).load(); 
			Log.d(this.getClass().getCanonicalName(), "Loading texture... "+sTextureName);
			 // 3 - Set up texture regions
			mTextureRegionTable.put(sTextureName, TextureRegionFactory.extractFromTexture(mTextureTable.get(sTextureName)));
		}
	}
	/**
	 * Inizializzo la scena di splash
	 * 
	 * 
	 * */
	public void initSplashScene(Scene oSceneGame)
	{
		this.mScene=oSceneGame;
		float SPRITE_X_SCALE = ((float)this.mWidth / ConstValue.F_SCREEN_WIDTH);
        float SPRITE_Y_SCALE = ((float)this.mHeight / ConstValue.F_SCREEN_HEIGHT);  
        
    	Sprite mSplash = new Sprite(0, 0, this.mResource.loadSplashTexture(this.mContext,this.mBaseGame), this.mBaseGame.getVertexBufferObjectManager())
    	{
    		@Override
            protected void preDraw(GLState pGLState, Camera pCamera) 
    		{
                super.preDraw(pGLState, pCamera);
                pGLState.enableDither();
            }
    	};
    	
    	mSplash.setScaleCenter(0, 0);
    	mSplash.setScale(SPRITE_X_SCALE, SPRITE_Y_SCALE);
    	this.mScene.attachChild(mSplash);
	}
	
	/**
	 * Carica in memoria tutte le risorse del Gioco
	 * 
	 * 
	 * */
	public boolean initMain(Scene oSceneGame,Engine mEngine){
		this.mScene=oSceneGame;
		float SPRITE_X_SCALE = ((float)this.mWidth / ConstValue.F_SCREEN_WIDTH);
        float SPRITE_Y_SCALE = ((float)this.mHeight / ConstValue.F_SCREEN_HEIGHT); 
        float pX=0f;
        float pY=0f;
        /**
         * Inizializzo l'audio della scena principale
         * sia gli effetti sonori che la musica di sottofondo
         *  
         * */
        mSoundTable= this.mResource.loadMainSoundFX(this.mContext, mEngine);
        mMusicTable= this.mResource.loadMainMusicFX(this.mContext, mEngine);
        
        Sprite mMain = new Sprite(0, 0, this.mResource.loadMainTexture(this.mContext,this.mBaseGame), this.mBaseGame.getVertexBufferObjectManager())
    	{
    		@Override
            protected void preDraw(GLState pGLState, Camera pCamera) 
    		{
                super.preDraw(pGLState, pCamera);
                pGLState.enableDither();
            }
    	};
    	mMain.setScaleCenter(0, 0);
    	mMain.setScale(SPRITE_X_SCALE, SPRITE_Y_SCALE);
		this.mScene.attachChild(mMain);
		Hashtable<String, TiledTextureRegion> mTiledTextureRegionTable = mResource.loadMainTexture(this.mContext,this.mBaseGame,mEngine);
		
		//TiledSprite main = new TiledSprite(0, 0, mTiledTextureRegionTable.get("main") , this.mBaseGame.getVertexBufferObjectManager());
		//this.mScene.attachChild(main);
		
		TiledSprite btn_start = new TiledSprite(100, 100, mTiledTextureRegionTable.get("btn_start") , this.mBaseGame.getVertexBufferObjectManager()) {
			 public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
			        Log.v(this.getClass().getCanonicalName(), "Sprite Touch btn_start");
			        //Riproduco il suono sul pulsante
			        //mSoundTable.get("click").play();
			        this.setCurrentTileIndex(1);
			        if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
			        	this.setCurrentTileIndex(0);
			        	//Passo a Caricare la Scena del gioco
			        	initGame(mScene);
			        }
			        return true;
			    }
		};
		
        btn_start.setScaleCenter(0, 0);
        btn_start.setScale(SPRITE_X_SCALE, SPRITE_Y_SCALE);
        pX=(this.mWidth/ConstValue.F_SCREEN_WIDTH)*ConstValue.F_BTN_START_OFFSET_X;
        pY=(this.mHeight/ConstValue.F_SCREEN_HEIGHT)*ConstValue.F_BTN_START_OFFSET_Y;
        btn_start.setPosition(pX, pY);
		this.mScene.attachChild(btn_start);
		
		TiledSprite btn_options = new TiledSprite(100, 100, mTiledTextureRegionTable.get("btn_options") , this.mBaseGame.getVertexBufferObjectManager()){
			 public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
			        Log.v(this.getClass().getCanonicalName(), "Sprite Touch btn_options");
			        //Riproduco il suono sul pulsante
			        //mSoundTable.get("click").play();
			        this.setCurrentTileIndex(1);
			        if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
			        	this.setCurrentTileIndex(0);
			        }
			        return true;
			    }
		};;
		btn_options.setScaleCenter(0, 0);
		btn_options.setScale(SPRITE_X_SCALE, SPRITE_Y_SCALE);
		pX=(this.mWidth/ConstValue.F_SCREEN_WIDTH)*ConstValue.F_BTN_OPTIONS_OFFSET_X;
        pY=(this.mHeight/ConstValue.F_SCREEN_HEIGHT)*ConstValue.F_BTN_OPTIONS_OFFSET_Y;
        btn_options.setPosition(pX, pY);
		this.mScene.attachChild(btn_options);
		
		TiledSprite btn_exit = new TiledSprite(200, 200, mTiledTextureRegionTable.get("btn_exit") , this.mBaseGame.getVertexBufferObjectManager()){
			 public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
			        Log.v(this.getClass().getCanonicalName(), "Sprite Touch btn_level");
			        //Riproduco il suono sul pulsante
			        //mSoundTable.get("click").play();
			        this.setCurrentTileIndex(1);
			        if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
			        	this.setCurrentTileIndex(0);
			        	System.exit(0);
			        }
			       
			        return true;
			    }
		};;
		btn_exit.setScaleCenter(0, 0);
		btn_exit.setScale(SPRITE_X_SCALE, SPRITE_Y_SCALE);
		pX=(this.mWidth/ConstValue.F_SCREEN_WIDTH)*ConstValue.F_BTN_EXIT_OFFSET_X;
        pY=(this.mHeight/ConstValue.F_SCREEN_HEIGHT)*ConstValue.F_BTN_EXIT_OFFSET_Y;
        btn_exit.setPosition(pX, pY);
		this.mScene.attachChild(btn_exit);
		
		TiledSprite btn_about = new TiledSprite(300, 300, mTiledTextureRegionTable.get("btn_about") , this.mBaseGame.getVertexBufferObjectManager()){
			 public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
			        Log.v(this.getClass().getCanonicalName(), "Sprite Touch btn_wall");
			        //Riproduco il suono sul pulsante
			        //mSoundTable.get("click").play();
			        this.setCurrentTileIndex(1);
			        if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
			        	this.setCurrentTileIndex(0);
			        }
			        return true;
			    }
		};;
		btn_about.setScaleCenter(0, 0);
		btn_about.setScale(SPRITE_X_SCALE, SPRITE_Y_SCALE);
		pX=(this.mWidth/ConstValue.F_SCREEN_WIDTH)*ConstValue.F_BTN_ABOUT_OFFSET_X;
        pY=(this.mHeight/ConstValue.F_SCREEN_HEIGHT)*ConstValue.F_BTN_ABOUT_OFFSET_Y;
        btn_about.setPosition(pX, pY);
		this.mScene.attachChild(btn_about);
		
		this.mScene.registerTouchArea(btn_start);
		this.mScene.registerTouchArea(btn_options);
		this.mScene.registerTouchArea(btn_exit);
		this.mScene.registerTouchArea(btn_about);				
		this.mScene.setTouchAreaBindingOnActionDownEnabled(true);
		
		return true;
	}
	
	/**
	 * Carica in memoria tutte le risorse del Gioco
	 * 
	 * 
	 * */
	public boolean initGame(Scene oSceneGame){
		this.mScene=oSceneGame;
		float SPRITE_X_SCALE = ((float)this.mWidth / ConstValue.F_SCREEN_WIDTH);
        float SPRITE_Y_SCALE = ((float)this.mHeight / ConstValue.F_SCREEN_HEIGHT); 
        
		Sprite backgroundSprite = new Sprite(0, 0, (ITextureRegion) this.mTextureRegionTable.get("background"), this.mBaseGame.getVertexBufferObjectManager());
		backgroundSprite.setScaleCenter(0, 0);
		backgroundSprite.setScale(SPRITE_X_SCALE, SPRITE_Y_SCALE);
		this.mScene.attachChild(backgroundSprite);
		
		//
		Vector<Sprite> vSprites = new Vector<Sprite>();
		//Sprite corvet = new Sprite(190, 100, this.mDestroyerTextureRegion, getVertexBufferObjectManager());
		Destroyer mDestroyer = new Destroyer(1, 0, 0, (ITextureRegion) this.mTextureRegionTable.get("destroyer"), this.mBaseGame.getVertexBufferObjectManager());
		Corvet mCorvet = new Corvet(1, 0, 0, (ITextureRegion) this.mTextureRegionTable.get("corvet"), this.mBaseGame.getVertexBufferObjectManager());
			this.mScene.attachChild(mDestroyer);
			this.mScene.attachChild(mCorvet);
			vSprites.add(mDestroyer);
			vSprites.add(mCorvet);

									
		this.mScene.setTouchAreaBindingOnActionDownEnabled(true);
		//SpriteTask task = new SpriteTask();
		//task.execute(vSprites);
		MoveEnemy(vSprites);
		return true;
	}
	/**
	 * Muove gli enemy in base ad in path definito, posso definirlo in base agli WAVE ed al 
	 * livello.
	 * 
	 * */
	private <IShape> void MoveEnemy(Vector<Sprite> vSrite){
		int iSize=vSrite.size();
		for(int i=0;i<iSize;i++){
			
			
			float pX[] = new float[LevelPath.F_X_LEVEL_PATH_1.length+1];
			for(int iFixCoo=0;iFixCoo<LevelPath.F_X_LEVEL_PATH_1.length-1;iFixCoo++){
				int iXOffSet = (int) (Math.random()*10);			
				pX[iFixCoo]=((this.mWidth/ConstValue.F_SCREEN_WIDTH)*LevelPath.F_X_LEVEL_PATH_1[iFixCoo])+iXOffSet;							
			}
			float pY[] = new float[LevelPath.F_Y_LEVEL_PATH_1.length+1];
			for(int iFixCoo=0;iFixCoo<LevelPath.F_Y_LEVEL_PATH_1.length-1;iFixCoo++){
				int iYOffSet = (int) (Math.random()*10);
				pY[iFixCoo]=((this.mHeight/ConstValue.F_SCREEN_HEIGHT)*LevelPath.F_Y_LEVEL_PATH_1[iFixCoo])+iYOffSet;
			}
			Path path = new Path(pX,pY);
			
			Sprite mSprite=vSrite.get(i);
		     /* Add the proper animation when a waypoint of the path is passed. */
			mSprite.registerEntityModifier(new LoopEntityModifier(new PathModifier(30, path, null, new IPathModifierListener() {

				@Override
				public void onPathStarted(PathModifier pPathModifier,
						IEntity pEntity) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void onPathWaypointStarted(PathModifier pPathModifier,
						IEntity pEntity, int pWaypointIndex) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void onPathWaypointFinished(PathModifier pPathModifier,
						IEntity pEntity, int pWaypointIndex) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void onPathFinished(PathModifier pPathModifier,
						IEntity pEntity) {
					Log.v(this.getClass().getCanonicalName(),"Path Finish");
					pEntity.setVisible(false);
					
				}}, EaseSineInOut.getInstance())));
		}
		
		    
	}
}
